﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Eneta.Portal.Common;
using Eneta.Portal.Common.Definitions;
using Eneta.Portal.Common.Repository;
using Microsoft.SharePoint;

namespace Eneta.Portal.Profiles.Controls
{
    public class ProfileEditControl : UserControl
    {
        protected Label titleLabel;
        protected Literal userNameLabel;
        protected Label headerUserNameLabel;
        protected System.Web.UI.WebControls.Image titleImage;
        protected HtmlAnchor titleLink;
        protected Button editButton;

        protected HtmlGenericControl MessageBox;
        protected Label MessageLabel;

        protected HtmlGenericControl firstNameContainer;
        protected HtmlGenericControl firstNameErrorMessage;
        protected HtmlGenericControl firstNameErrorNote;
        protected TextBox firstNameField;
        protected CheckBox showFirstName;
        protected TextBox lastNameField;
        protected CheckBox showLastName;
        protected TextBox emailField;
        protected CheckBox showEmail;

        protected HtmlGenericControl interestsContainer;
        protected HtmlGenericControl interestsErrorMessage;
        protected HtmlGenericControl interestsErrorNote;
        protected CheckBoxList interestsList;

        protected TextBox aboutField;
        protected System.Web.UI.WebControls.Image profileImage;
        protected FileUpload profileImageUpload;
        protected TextBox homePageUrlField;
        protected TextBox addressField;
        protected CheckBox showAddress;
        protected TextBox phoneField;
        protected CheckBox showPhone;

        protected TextBox schoolField;
        protected CheckBox showSchool;
        protected TextBox fieldOfStudyField;
        protected CheckBox showFieldOfStudy;

        protected TextBox companyField;
        protected CheckBox showCompany;
        protected TextBox jobTitleField;
        protected CheckBox showJobTitle;

        protected CheckBox sendMsInfo;
        protected CheckBox sendEventsInfo;
        protected Button saveButton;


        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            saveButton.Click += SaveButtonClick;

        }



        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            HideErrors(Controls);

            var currentUser = SPContext.Current.Web.CurrentUser;

            if (currentUser == null)
            {
                Response.Redirect("/");
                return;
            }

            if (Item == null)
                return;

            var nameParts = currentUser.LoginName.ToLower().Split('|');
            var userName = nameParts[nameParts.Length- 1];
            

            if (Item["SysID"].ToString().ToLower() != userName)
                if (!currentUser.IsSiteAdmin)
                {
                    Response.Redirect("/");
                    return;
                }

            Page.Title = currentUser.Name + " > Muuda profiili | Microsoft Eneta";

            MessageBox.Visible = false;

            var msg = Request.QueryString["msg"] ?? string.Empty;

            switch (msg)
            {
                case "joined":
                    MessageLabel.Text = Resources.GetResourceString("Message_Joined");
                    break;
                case "missingflds":
                    MessageLabel.Text = Resources.GetResourceString("Message_MissingFields");
                    MessageBox.Attributes["class"] = "slide-box warning";
                    break;
                default:
                    msg = string.Empty;
                    break;
            }

            MessageBox.Visible = !string.IsNullOrEmpty(msg);
            //MessageBox.Attributes["class"] = "slide-box success";

            if (IsPostBack)
                return;
            Bind();
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (homePageUrlField.Text == string.Empty)
                homePageUrlField.Text = "http://";
            if (homePageUrlField.Text.ToLower() == "http://")
                homePageUrlField.CssClass = "text-go clear";
            else
                homePageUrlField.CssClass = "text-go";

            SetCheckStyles(Controls);
        }

        private static void SetCheckStyles(ControlCollection controls)
        {
            foreach (Control c in controls)
                if (c.GetType() == typeof(CheckBox))
                    ((CheckBox)c).InputAttributes["class"] = "choice";
                else if (c.HasControls())
                    SetCheckStyles(c.Controls);

        }
        private SPListItem _item;

        private SPListItem Item
        {
            get
            {
                if (_item != null)
                    return _item;

                var idString = Request.QueryString["profileID"];
                if (string.IsNullOrEmpty(idString))
                    return null;

                int id;
                if (!int.TryParse(idString, out id))
                    return null;

                _item = SPContext.Current.Web.GetList(Lists.ProfileList).GetItemById(id);
                return _item;
            }
        }

        private void Bind()
        {
            var item = Item;
            headerUserNameLabel.Text = item.Title;
            titleLabel.Text = item.Title;
            titleLink.HRef = EnetaApplication.PortalProfilePageUrl + "?profileID=" + item.ID;

            firstNameField.Text = item.GetFieldString(UserProfileFields.FirstName);
            showFirstName.Checked = item.GetFieldBool(UserProfileFields.ShowFirstName);
            lastNameField.Text = item.GetFieldString(UserProfileFields.LastName);
            showLastName.Checked = item.GetFieldBool(UserProfileFields.ShowLastName);
            emailField.Text = item.GetFieldString(UserProfileFields.Email);
            showEmail.Checked = item.GetFieldBool(UserProfileFields.ShowEmail);
            
            interestsList.Items.Clear();

            var choiceField = (SPFieldMultiChoice)item.Fields[item.FieldIdOf(UserProfileFields.MyInterests)];
            var choiceValue = new SPFieldMultiChoiceValue((string)item.ValueOf(UserProfileFields.MyInterests));

            foreach (string choice in choiceField.Choices)
            {
                var listItem = new ListItem
                {
                    Text = choice,
                    Value = choice
                };

                for (var i = 0; i < choiceValue.Count; i++)
                    if (choice == choiceValue[i])
                    {
                        listItem.Selected = true;
                        break;
                    }
                interestsList.Items.Add(listItem);
            }

            aboutField.Text = item.GetFieldString(UserProfileFields.AboutMe);

            var profileRepository = new UserProfileRepository(SPContext.Current.Web);
            var profile = profileRepository.GetUserProfileById(item.ID);
            titleImage.ImageUrl = profile.UserImage32x32Url; 
            profileImage.ImageUrl = titleImage.ImageUrl;
            homePageUrlField.Text = profile.Blog;
            addressField.Text = profile.Address;
            showAddress.Checked = profile.ShowAddress;
            phoneField.Text = profile.Phone;
            showPhone.Checked = profile.ShowPhone;
            schoolField.Text = profile.School;
            showSchool.Checked = profile.ShowSchool;
            fieldOfStudyField.Text = profile.FieldOfStudy;
            showFieldOfStudy.Checked = profile.ShowFieldOfStudy;
            companyField.Text = profile.Company;
            showCompany.Checked = profile.ShowCompany;
            jobTitleField.Text = profile.JobTitle;
            showJobTitle.Checked = profile.ShowJobTitle;
            sendEventsInfo.Checked = profile.SendEventsInfo;
            sendMsInfo.Checked = profile.SendMsInfo;
        }

        private void SaveButtonClick(object sender, EventArgs e)
        {

            var errors = new Dictionary<string, string>();

            if (string.IsNullOrEmpty(firstNameField.Text))
            {
                errors.Add("firstName", Resources.GetResourceString("FirstNameIsRequired"));
            }
            else if (firstNameField.Text.Length < 2)
            {
                errors.Add("firstName", Resources.GetResourceString("FirstNameIsTooShort"));
            }
            else if (firstNameField.Text.Length > 25)
            {
                errors.Add("firstName", Resources.GetResourceString("FirstNameIsTooLong"));
            }

            // Perenimi
            if (string.IsNullOrEmpty(lastNameField.Text))
            {
                errors.Add("lastName", Resources.GetResourceString("LastNameIsRequired"));
            }
            else if (lastNameField.Text.Length < 2)
            {
                errors.Add("lastName", Resources.GetResourceString("LastNameIsTooShort"));
            }
            else if (lastNameField.Text.Length > 25)
            {
                errors.Add("lastName", Resources.GetResourceString("LastNameIsTooLong"));
            }

            // E-mail
            var emailRegEx = @"^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$";
            if (string.IsNullOrEmpty(emailField.Text))
            {
                errors.Add("email", "");
            }
            else if (emailField.Text.Length > 100)
            {
                errors.Add("email", Resources.GetResourceString("EmailIsTooLong"));
            }
            else if (!Regex.IsMatch(emailField.Text, emailRegEx))
            {
                errors.Add("email", Resources.GetResourceString("EmailIsIncorrect"));
            }

            // Huvid
            var selectedInterests = GetSelectedInterests();
            interestsErrorMessage.Visible = false;
            interestsErrorNote.Visible = false;
            if (selectedInterests.Length == 0)
            {
                errors.Add("interests", Resources.GetResourceString("SelectionIsRequired"));
            }

            // Profiili pilt
            if (profileImageUpload.HasFile)
            {
                try
                {
                    using (var mem = new MemoryStream())
                    {
                        mem.Write(profileImageUpload.FileBytes, 0, profileImageUpload.FileBytes.Length);
                        var bmp = System.Drawing.Image.FromStream(mem);
                        bmp.Dispose();
                    }
                }
                catch
                {
                    errors.Add("photo", Resources.GetResourceString("ImageUploadFailed"));
                }
            }

            if (errors.Count > 0)
            {
                ApplyErrors(errors);
                return;
            }

            var siteId2 = SPContext.Current.Site.ID;
            var userId = SPContext.Current.Web.CurrentUser.ID;
            var sec2 = new SPSecurity.CodeToRunElevated(() => Save(siteId2, userId));
            SPSecurity.RunWithElevatedPrivileges(sec2);

            Response.Redirect(EnetaApplication.PortalProfilePageUrl+"?profileID=" + Request.QueryString["profileID"] + "&msg=saved");
        }
        private void Save(Guid siteId, int userId)
        {
            using (var xSite = new SPSite(siteId))
            {
                using (var web = xSite.OpenWeb())
                {
                    Logger.LogInfo("Save(): Starting");

                    var list = web.GetList(Lists.ProfileList);
                    var xItem = list.GetItemById(Item.ID);
                    //var xDigestSettings = xSite.WebApplication.FormDigestSettings;
                    //var xSettingsEnable = xDigestSettings.Enabled;
                    xSite.AllowUnsafeUpdates = true;
                    web.AllowUnsafeUpdates = true;

                    Logger.LogInfo("Save(): Assigning values - main");

                    xItem.SetValue(UserProfileFields.FirstName, firstNameField.Text);
                    xItem.SetValue(UserProfileFields.ShowFirstName, showFirstName.Checked);
                    xItem.SetValue(UserProfileFields.LastName, lastNameField.Text);
                    xItem.SetValue(UserProfileFields.ShowLastName, showLastName.Checked);
                    xItem.SetValue(UserProfileFields.Email, emailField.Text);
                    xItem.SetValue(UserProfileFields.ShowEmail, showEmail.Checked);

                    var interestsValue = new SPFieldMultiChoiceValue();
                    foreach (var interest in GetSelectedInterests())
                        interestsValue.Add(interest);
                    xItem.SetValue(UserProfileFields.MyInterests, interestsValue);
                    xItem.SetValue(UserProfileFields.AboutMe, aboutField.Text);

                    if (!string.IsNullOrEmpty(homePageUrlField.Text) && homePageUrlField.Text != "http://")
                    {
                        var url = homePageUrlField.Text;
                        if (!url.ToLower().StartsWith("http://") && !url.ToLower().StartsWith("https://"))
                            url = "http://" + url;
                        var homePageValue = new SPFieldUrlValue
                        {
                            Description = homePageUrlField.Text,
                            Url = url
                        };
                        xItem.SetValue(UserProfileFields.Homepage, homePageValue);
                    }
                    else
                        xItem.SetValue(UserProfileFields.Homepage, null);

                    Logger.LogInfo("Save(): Assigning values - address and phone");
                    xItem.SetValue(UserProfileFields.Address, addressField.Text);
                    xItem.SetValue(UserProfileFields.ShowAdddress, showAddress.Checked);
                    xItem.SetValue(UserProfileFields.Phone, phoneField.Text);
                    xItem.SetValue(UserProfileFields.ShowPhone, showPhone.Checked);

                    Logger.LogInfo("Save(): Assigning values - school");
                    xItem.SetValue(UserProfileFields.School, schoolField.Text);
                    xItem.SetValue(UserProfileFields.ShowSchool, showSchool.Checked);
                    xItem.SetValue(UserProfileFields.FieldOfStudy, fieldOfStudyField.Text);
                    xItem.SetValue(UserProfileFields.ShowFieldOfStudy, showFieldOfStudy.Checked);

                    Logger.LogInfo("Save(): Assigning values - work");
                    xItem.SetValue(UserProfileFields.Company, companyField.Text);
                    xItem.SetValue(UserProfileFields.ShowCompany, showCompany.Checked);
                    xItem.SetValue(UserProfileFields.JobTitle, jobTitleField.Text);
                    xItem.SetValue(UserProfileFields.ShowJobTitle, showJobTitle.Checked);

                    Logger.LogInfo("Save(): Assigning values - events and info");
                    xItem.SetValue(UserProfileFields.SendEventsInfo, sendEventsInfo.Checked);
                    xItem.SetValue(UserProfileFields.SendMsInfo, sendMsInfo.Checked);

                    if (profileImageUpload.HasFile)
                    {
                        Logger.LogInfo("Save(): Creating 32x32 image");
                        var stream = new MemoryStream();
                        ResizeImage(32, profileImageUpload.FileContent, stream);
                        var thumb = stream.ToArray();
                        stream.Dispose();

                        Logger.LogInfo("Save(): Creating 16x16 image");
                        stream = new MemoryStream();
                        ResizeImage(16, profileImageUpload.FileContent, stream);
                        var smallThumb = stream.ToArray();
                        stream.Dispose();

                        Logger.LogInfo("Save(): Creating 64x64 image");
                        stream = new MemoryStream();
                        ResizeImage(64, profileImageUpload.FileContent, stream);
                        var largeThumb = stream.ToArray();
                        stream.Dispose();

                        Logger.LogInfo("Save(): Removing attachments");
                        xItem.Attachments.RemoveAll();

                        Logger.LogInfo("Save(): Adding images as attachments");

                        var files = web.GetFolder("/SiteCollectionImages/users/").Files;
                        var filePrefix = files.Folder.Url + "/" + xItem.ID + "_";
                        files.Add(filePrefix + "16x16.png", smallThumb, true);
                        files.Add(filePrefix + "32x32.png", thumb, true);
                        files.Add(filePrefix + "64x64.png", largeThumb, true);

                        var profileRepository = new UserProfileRepository(web);
                        profileRepository.RemoveFromCache(xItem.ID);
                    }

                    try
                    {
                        xItem.Update();
                        xItem.ParentList.Update();


                        //xDigestSettings.Enabled = xSettingsEnable;
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning("Save(): Error saving profile");
                        Logger.LogException(ex);
                    }

                    var profRep = new UserProfileRepository(SPContext.Current.Web);
                    var fillmentPercent = profRep.GetUserProfileFillmentPercent(xItem);
                    if (xItem.ValueOf(UserProfileFields.ProfileFilledDate) == null)
                        if (fillmentPercent == 100)
                        {
                            xItem.SetValue(UserProfileFields.ProfileFilledDate, DateTime.Now);
                            xItem.Update();
                        }

                    var rep = new UserProfileRepository(SPContext.Current.Web);
                    try
                    {
                        SPUser user = null;
                        foreach (SPUser spuser in web.Users)
                            if (spuser.ID == userId)
                            {
                                user = spuser;
                                break;
                            }
                        if (user != null)
                        {
                            
                            var userItem = rep.GetUserProfileByUserName(user.LoginName, true);

                            Cache["User:" + user.LoginName] = userItem;
                            user.Email = emailField.Text;
                            user.Name = userItem.UserName;
                            user.Update();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogInfo("Save(): error editing SP user - id: " + userId);
                        Logger.LogException(ex);
                        throw;
                    }

                    rep.RemoveFromCache(Item.ID);
                }
            }

            _item = null;
            Response.Redirect(EnetaApplication.PortalProfileEditPageUrl+"?profileID=" + Request.QueryString["profileID"], false);
        }

        private void ApplyErrors(Dictionary<string, string> errors)
        {
            if (errors == null)
                return;

            if (errors.Count > 0)
            {
                MessageLabel.Text = Resources.GetResourceString("PleaseFillAllRequiredFields");
                MessageBox.Visible = true;
                MessageBox.Attributes["class"] = "slide-box warning";
            }

            foreach (var fieldKey in errors.Keys)
            {
                var error = errors[fieldKey];
                var ctl = (HtmlGenericControl)Page.FindControl(fieldKey + "Container", true);
                if (ctl != null)
                    ctl.Attributes.Add("class", "info-row failed-info");

                ctl = (HtmlGenericControl)Page.FindControl(fieldKey + "ErrorMessage", true);
                if (ctl != null)
                    ctl.Visible = true;

                ctl = (HtmlGenericControl)Page.FindControl(fieldKey + "ErrorLabel", true);
                if (ctl != null)
                {
                    ctl.InnerText = error;
                    ctl.Visible = true;
                }
            }
        }

        private string[] GetSelectedInterests()
        {
            var interests = new List<string>();
            foreach (ListItem item in interestsList.Items)
            {
                if (item.Selected)
                    interests.Add(item.Value);
            }
            return interests.ToArray();
        }

        private static void ResizeImage(int sideLength, Stream fromStream, Stream toStream)
        {
            using (var image = System.Drawing.Image.FromStream(fromStream))
            using (var thumbnailBitmap = new Bitmap(sideLength, sideLength))
            {
                var a = Math.Min(image.Width, image.Height);
                var x = (image.Width - a) / 2;
                var y = (image.Height - a) / 2;

                using (var thumbnailGraph = Graphics.FromImage(thumbnailBitmap))
                {
                    thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
                    thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
                    thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

                    var imageRectangle = new Rectangle(0, 0, sideLength, sideLength);
                    thumbnailGraph.DrawImage(image, imageRectangle, x, y, a, a, GraphicsUnit.Pixel);
                    thumbnailBitmap.Save(toStream, ImageFormat.Png);
                }
            }
        }

        private void HideErrors(ControlCollection ctls)
        {
            foreach (Control c in ctls)
            {
                if (c == null)
                    continue;
                if (string.IsNullOrEmpty(c.ID))
                    goto childnodes;
                if (!c.ID.EndsWith("Container") && !c.ID.EndsWith("ErrorLabel") && !c.ID.EndsWith("ErrorMessage"))
                    goto childnodes;

                c.Visible = false;

                if (c.ID.EndsWith("Container"))
                {
                    var ctl = (HtmlGenericControl)c;
                    ctl.Attributes["class"] = "info-row";
                    ctl.Visible = true;
                }

            childnodes:
                if (c.HasControls())
                    HideErrors(c.Controls);
            }
        }

    }
}
